//----------------------------------------------------------------------------
//  ,-.
// /_\___ ,   Ninja Framework
// '  ___\    (C) Riccardo Capra - http://riccar.do
//  //   \\
//----------------------------------------------------------------------------
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------------

#ifndef NJ_PLATFORM_SYNC_OBJECT_H
#	define NJ_PLATFORM_SYNC_OBJECT_H

#	include "NjExample01.h"

	/// \brief Implements a fast platform specific synchronization object
	///
	/// This interface is used for performances comparison
	class NjPlatformSyncObject
	{
	public:
		/// \copydoc NjEventsSystem::TimeMs
		typedef NjEventsSystem::TimeMs TimeMs;

		/// \typedef SyncObject
		/// \brief Defines the platform specific synchronization object

#       if NJ_PLATFORM_OS_WIN
		typedef CRITICAL_SECTION SyncObject;
#       elif NJ_PLATFORM_OS_LINUX
		typedef pthread_mutex_t SyncObject;
#	else // NJ_PLATFORM_OS_WIN || NJ_PLATFORM_OS_LINUX
#		error "Unsupported platform configuration"
#	endif // NJ_PLATFORM_OS_WIN || NJ_PLATFORM_OS_LINUX

		/// \brief Initializes the platform-specific synchronization object
		/// \param kSyncObject The buffer to be initialized
		static void Initialize(SyncObject & kSyncObject);

		/// \brief Locks the platform-specific synchronization object
		/// \param kSyncObject The platform-specific synchronization object to be locked
		static void Lock(SyncObject & kSyncObject);

		/// \brief Attempts locking the platform-specific synchronization object
		///
		/// If the object is locked within \em uTimeMs milliseconds, NJ_TRUE will be returned.
		/// If the object is not locked within \em uTimeMs milliseconds, NJ_FALSE will be returned
		/// \param kSyncObject The platform-specific synchronization object to be locked
		/// \param uTimeMs The time out in milliseconds
		static NjBool TryLock(SyncObject & kSyncObject, TimeMs uTimeMs);

		/// \brief Unlocks the platform-specific synchronization object
		/// \param kSyncObject The platform-specific synchronization object to be unlocked
		static void Unlock(SyncObject & kSyncObject);

		/// \brief Deinitializes the platform-specific synchronization object
		/// \param kSyncObject The platform-specific synchronization object to be deinitialized
		static void Destroy(SyncObject & kSyncObject);

		/// \brief Returns the platform-specific synchronization object name (for performance charts)
		static NjCharA const * GetName();

	private:
		NJ_DISABLE_INSTANCE(NjPlatformSyncObject);
	};

#	if NJ_PLATFORM_OS_WIN
#		include "NjPlatformSyncObjectWin_inline.h"
#	elif NJ_PLATFORM_OS_LINUX
#		include "NjPlatformSyncObjectLinux_inline.h"
#	else // NJ_PLATFORM_OS_WIN || NJ_PLATFORM_OS_LINUX
#		error "Unsupported platform configuration"
#	endif // NJ_PLATFORM_OS_WIN || NJ_PLATFORM_OS_LINUX

#endif // NJ_PLATFORM_SYNC_OBJECT_H
